package org.schat;

import com.alibaba.fastjson.JSONObject;
import org.schat.utils.RSAUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * @Description 客户端
 * @Author lsh
 * @Date 2020-03-18 19:16
 **/
public class IMClient {
    private static Socket socket;
    private static JPanel topPanel;
    private static JPanel bottomPanel;
    private static JPanel middlePanel;
    private static JTextArea receivedjTextArea;
    private static JTextArea sendTextArea;
    private static JLabel onlineNumLabel;

    public static void main(String[] args) {
        createUI();
		try {
		    socket=new Socket("127.0.0.1", 10086);
            authorization(socket);
			Thread receiveThread=new Thread(){
				@Override
				public void run() {
					receiveServerMsg(socket);
				}
			};
			receiveThread.start();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static void authorization(Socket socket){
	    String str = "hello world!";
        String encodedData = "";
        try {
            encodedData = RSAUtils.publicEncrypt(str, RSAUtils.getPublicKey(Constant.CLIENT_PUBLIC_KEY));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        sendMsgToServer(socket,"0",encodedData);
    }
	
	public static void sendMsgToServer(Socket socket,String type,String msg){
		try {
            JSONObject jsonObject =  new JSONObject();
            jsonObject.put("type",type);
            jsonObject.put("msg",msg);
			OutputStream output = socket.getOutputStream();
			output.write(jsonObject.toJSONString().getBytes("UTF-8"));
			output.write('\n');
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static void receiveServerMsg(Socket socket){
		try {
			ByteArrayOutputStream out=new ByteArrayOutputStream();
			InputStream is = socket.getInputStream();
			int b;
			while((b=is.read())!=-1){
				char c=(char)b;
				if(c !='\n') {
					out.write(b);
				}else {
					String dataMsg=new String(out.toByteArray(),"UTF-8");
					JSONObject jsonObject = (JSONObject)JSONObject.parse(dataMsg);
					if(jsonObject !=null ){
						String msg = (String)jsonObject.get("msg");
						String type = (String)jsonObject.get("type");
						//连接建立成功！
						if("0".equals(type) && "1000".equals(msg)){
						    //发送心跳数据包
							keepHeartBeat(socket);

						}else if("1".equals(type)){
						    //收到群聊
                            receivedjTextArea.append("\n");
                            receivedjTextArea.append(msg);
                            receivedjTextArea.setCaretPosition(receivedjTextArea.getDocument().getLength());

                        }else if("3".equals(type)){
						    //更新在线数量
						    JSONObject onlineInfo = (JSONObject) JSONObject.parse(msg);
                            Integer onlineNum = (Integer)onlineInfo.get("onlineNum");
                            onlineNumLabel.setText(onlineNum+"");
                        }else if("4".equals(type)){
						    //灭霸的响指
                            JSONObject thanosInfo = (JSONObject) JSONObject.parse(msg);
                            String resultCode = (String) thanosInfo.get("resultCode");
                            if("1".equals(resultCode)){
                                //发动成功
                                JOptionPane.showMessageDialog(null,"灭霸的响指发动成功！");
                            }else if("2".equals(resultCode)){
                                //发动失败
                                JOptionPane.showMessageDialog(null,"发动失败，已经有其他用户发动了灭霸的响指，请稍后再试！");
                            }else if("8888".equals(resultCode)){
                                //回复服务器发来的消息,完成后续操作
                                String thanosVersion = (String)thanosInfo.get("thanosVersion");
                                JSONObject parameter = new JSONObject();
                                parameter.put("isFirst",false);
                                parameter.put("thanosVersion",thanosVersion);
                                sendMsgToServer(socket,"4",parameter.toJSONString());
                            }else if("-9999".equals(resultCode)){
                                //被灭霸的响指消灭
                                JOptionPane.showMessageDialog(null,"你被灭霸的响指消灭了！");
                                //退出程序
                                System.exit(0);
                            }
                        }
					}

					out.reset();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void keepHeartBeat(final Socket socket){
        Thread keepHeartBeatThread=new Thread(){
            @Override
            public void run() {
                while(!socket.isClosed()){
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    sendMsgToServer(socket,"2","keepLive");
                }
            }
        };
        keepHeartBeatThread.start();
    }

    private static void createTopPanel() {
        topPanel = new JPanel();

        receivedjTextArea = new JTextArea();
        receivedjTextArea.setEditable(false);
        receivedjTextArea.setLineWrap(true);
        receivedjTextArea.setWrapStyleWord(true);
        JScrollPane scrollPane = new JScrollPane(receivedjTextArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));
        topPanel.add(Box.createVerticalStrut(10));
        topPanel.add(scrollPane);
        topPanel.add(Box.createVerticalStrut(10));
    }

    private static void createMiddlePanel(){
        sendTextArea= new JTextArea();
        addSendTextAreKeyboardListener();
        middlePanel = new JPanel();
        //middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.X_AXIS));
        middlePanel.setLayout(new BoxLayout(middlePanel, BoxLayout.Y_AXIS));

        JScrollPane scrollPane = new JScrollPane(sendTextArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);


        middlePanel.add(Box.createVerticalStrut(10));
        middlePanel.add(scrollPane);
        middlePanel.add(Box.createVerticalStrut(10));
    }

    private static void createBottomPanel() {
        JButton actionButton = new JButton("发送");
        JButton closeButton = new JButton("退出");
        JButton thanosButton = new JButton("灭霸的响指");
        addSendMsgActionListener(actionButton);
        addQuitActionListener(closeButton);
        addThanosActionListener(thanosButton);

        bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.Y_AXIS));

        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
        JLabel onLineTextLabel = new JLabel("在线沙雕数：");
        onlineNumLabel = new JLabel("0");
        buttonPanel.add(actionButton);
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(onLineTextLabel);
        buttonPanel.add(onlineNumLabel);
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(thanosButton);
        buttonPanel.add(Box.createHorizontalGlue());
        buttonPanel.add(closeButton);

        bottomPanel.add(Box.createVerticalStrut(10));
        bottomPanel.add(buttonPanel);
        bottomPanel.add(Box.createVerticalStrut(10));
    }

    private static void sendMsg(){
        String message = sendTextArea.getText();
        message = message.replace("\n","");
        if(!"".equals(message)){
            sendMsgToServer(socket,"1",message);
            sendTextArea.setText("");
        }
    }

    private static void addSendMsgActionListener(JButton actionButton){
        actionButton.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                sendMsg();
            }
        });
    }

    private static void addQuitActionListener(JButton actionButton){
        actionButton.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }

    private static void addThanosActionListener(JButton actionButton){
        actionButton.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                JSONObject parameter = new JSONObject();
                parameter.put("isFirst",true);
                sendMsgToServer(socket,"4",parameter.toJSONString());
            }
        });
    }

    private static void addSendTextAreKeyboardListener(){
        sendTextArea.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {}

            @Override
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode() == 10){
                    sendMsg();
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {}
        });

    }

    private static void createUI(){
        createTopPanel();
        createMiddlePanel();
        createBottomPanel();

        JPanel panelContainer = new JPanel();
        panelContainer.setLayout(new GridBagLayout());

        GridBagConstraints c1 = new GridBagConstraints();
        c1.gridx = 0;
        c1.gridy = 0;
        c1.weightx = 1.0;
        c1.weighty = 1.0;

        c1.fill = GridBagConstraints.BOTH;
        panelContainer.add(topPanel, c1);

        GridBagConstraints c2 = new GridBagConstraints();
        c2.gridx = 0;
        c2.gridy = 1;
        c2.weightx = 1.0;
        c2.weighty = 0;
        c2.fill = GridBagConstraints.HORIZONTAL;
        panelContainer.add(middlePanel, c2);

        GridBagConstraints c3 = new GridBagConstraints();
        c3.gridx = 0;
        c3.gridy = 2;
        c3.weightx = 1.0;
        c3.weighty = 0;
        c3.fill = GridBagConstraints.HORIZONTAL;
        panelContainer.add(bottomPanel, c3);

        JFrame jFrame = new JFrame("沙雕聊天室");
        jFrame.setBounds(0,0,400,500);
        jFrame.setContentPane(panelContainer);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
    }

}
